/**
 * @format
 * @Author: TC
 * @Date: 2023-07-27 16:51:27
 * @Last Modified by: TC
 * @Last Modified time: 2025-05-05 01:47:44
 */

import { BufferAsset, sys } from "cc";
import { app } from "../App";

export interface BinFileData {
    /**文件名称 */
    name: string;
    /**文件内容文本 */
    text: string;
}

/**
 * 处理bin文件通用接口
 */
export namespace nsBin {
    /**
     * bin文件解压后文本内容
     */
    type CfgsBinType = {
        curIdx: number;
        okNum: number;
        totNum: number;
        stepFunc: Function;
        allOverFunc: Function;
        uint8Array: Uint8Array;
        cfgDict: any;
        strList: BinFileData[];
    };

    /**
     * 解析bin的zip数据
     * @param headLen
     * @param array
     * @returns
     */
    export function decodeCfgZipBuffer(headLen: number, array: Uint8Array): Uint8Array {
        let len = array.length - headLen;
        for (let i = 0; i < len; i++) {
            array[headLen + i] ^= 255;
        }
        return array;
    }

    /**
     * js解压配置文件
     * @param info
     * @param cb
     */
    function _prepareCfgBinJs(info: CfgsBinType, cb: () => void) {
        let totNum = 0;
        let stepFunc = null;
        let allOverFunc = () => {};
        app.jsZip.jsZipGetData(info.uint8Array.buffer, (zip, configKeyArray) => {
            totNum = configKeyArray.length;
            stepFunc = (overCb: Function) => {
                let key = configKeyArray[info.curIdx];
                let name = key.split(".")[0];
                zip.file(key)
                    .async("string")
                    .then((textData: string) => {
                        info.strList.push({ name: name, text: textData });
                        overCb();
                    });
            };
            info.totNum = totNum;
            info.stepFunc = stepFunc;
            info.allOverFunc = allOverFunc;
            cb();
        });
    }

    /**
     * cpp解压配置文件
     */
    function _prepareCfgBinCpp(info: CfgsBinType, cb: () => void) {
        let unzipExtend = new window["UnzipExtend"]() as any;
        let totNum = unzipExtend.unzipBuffer(info.uint8Array);
        let allOverFunc = () => {
            //关闭unzip
            unzipExtend.unzipClose();
            unzipExtend = null;
        };
        let stepFunc = (overCb: Function) => {
            let fileInfo = unzipExtend.getNextZipFile();
            let key = fileInfo.fileName;
            let name = key.split(".")[0];
            info.strList.push({ name: name, text: fileInfo.fileContent });
            fileInfo = null;
            overCb();
        };
        info.totNum = totNum;
        info.stepFunc = stepFunc;
        info.allOverFunc = allOverFunc;
        cb();
    }

    /**
     * 解析bin文件
     * @param bufferAsset
     * @param cb 解析完成的回调
     */
    export function parseBin(bufferAsset: BufferAsset, cb: (strList: BinFileData[]) => void) {
        let cfgBinBuffer = new Uint8Array((bufferAsset as any)._buffer);
        let info = {
            curIdx: 0,
            okNum: 0,
            totNum: 0,
            stepFunc: null,
            allOverFunc: null,
            uint8Array: cfgBinBuffer,
            cfgDict: {},
            strList: [],
        };

        let stepOverFunc = () => {
            let tmpIdx = 0;
            let tmpTot = 5;
            for (let i = 1; i <= tmpTot; i++) {
                if (info && info.curIdx < info.totNum) {
                    tmpIdx += 1;
                    info.stepFunc(() => {
                        info.okNum += 1;
                        if (info.okNum < info.totNum) {
                            if (tmpIdx == tmpTot) {
                                tmpIdx = 0;
                                stepOverFunc();
                            }
                        } else {
                            info.allOverFunc();
                            let strList = info.strList;
                            cfgBinBuffer = null;
                            info = null;
                            cb(strList);
                            strList = null;
                        }
                    });
                    //H5stepFunc是异步的,App是同步的，如果是全部完成，则会把info置为null
                    info && info.curIdx++;
                } else {
                    return;
                }
            }
        };
        let func = _prepareCfgBinJs;
        if (sys.isNative && window["UnzipExtend"]) {
            func = _prepareCfgBinCpp;
        }
        func(info, () => {
            stepOverFunc();
        });
    }
}
